////////////////////////////////////////////////////////////////////////////
//
//  CryEngine Source File.
//  Copyright (C), Crytek.
// -------------------------------------------------------------------------
//  File name:   StreamAsyncFileRequest.h
//  Created:     22/07/2010 by Timur.
//  Description: Streaming Thread for IO
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#ifndef __StreamAsyncFileRequest_h__
#define __StreamAsyncFileRequest_h__
#pragma once

#include <IStreamEngine.h>

class CStreamEngine;
class CAsyncIOFileRequest;

enum EStreamSourceMediaType
{
	eStreamSourceTypeHDD = 0,
	eStreamSourceTypeDisc,
	eStreamSourceTypeMemory,
	eStreamSourceTypeNum,
};

struct IAsyncIOFileCallback
{
	virtual ~IAsyncIOFileCallback(){}
	// Asynchronous finished event.
	// Must be thread safe, can be called from a different thread.
	virtual void OnAsyncFinished( CAsyncIOFileRequest *pFileRequest ) = 0;
};

// This class represent a request to read some file from disk asynchronously via one of the IO threads.
class CAsyncIOFileRequest : public CMultiThreadRefCount
{
public:
	enum EStatus
	{
		eStatusNotReady,
		eStatusInFileQueue,
		eStatusReadComplete,
		eStatusFailed,
		eStatusUnzipComplete,
		eStatusDone,
	};

	CAsyncIOFileRequest( EStreamTaskType eType );
	~CAsyncIOFileRequest();

	void ReadFile();
	void ReadFailed( int nErrorCode );
	void ReadComplete();
	bool Decompress();
	void Cancel();
	void Done();
	void ComputeSortKey(uint64 nCurrentKeyInProgress);
	void FreeBuffer();

	bool IgnoreOutofTmpMem() const;

	ILINE bool IsCanceled() const { return m_bCanceled != 0; }

	CStreamEngine* GetStreamEngine();

	EStreamSourceMediaType GetMediaType();

public:
	uint64 m_nSortKey;

	EStreamTaskPriority m_ePriority;
	EStreamSourceMediaType m_eMediaType;
	EStreamTaskType m_eType;

	volatile EStatus m_status;
	uint32 m_nErrorCode;
	uint32 m_bCanceled;

	uint32 m_nRequestedOffset;
	uint32 m_nRequestedSize;
	uint32 m_nFlags; // StreamReadParamsFlagEnum

	CryStringLocal m_strFileName;
	string m_pakFile;

	// the file size, or 0 if the file couldn't be opened
	uint32 m_nFileSize;
	uint32 m_nFileSizeCompressed;

	void* m_pExternalMemoryBuffer;
	void* m_pOutputMemoryBuffer;

	// Lock to be held whilst the file is being read, and an external memory buffer is in use
	// (to ensure that if cancelled, the stream engine doesn't write to the external buffer)
	CryCriticalSection m_externalBufferLock;

	IMemoryBlock_AutoPtr m_pMemoryBuffer;

	uint32 m_bCompressedBuffer : 1;
	uint32 m_bDecompressInPlace : 1;
	uint32 m_bNoSorting        : 1; // When set assign sequential sort order
	uint32 m_bStatsUpdated     : 1; // When set assign sequential sort order
	uint32 m_bSortKeyComputed : 1;

	uint32 m_nReadCounter;

	// Actual size of the data on the media.
	uint32 m_nSizeOnMedia;

	int64 m_nDiskOffset;
	int32 m_nReadHeadOffsetKB; // Offset of the Read Head when reading from media.
	int32 m_nTimeGroup;

	// If not 0, and file size on disk is bigger then this cancel file request.
	uint32 m_maxFileSize;

	// Time that read operation took.
	CTimeValue m_readTime;
	CTimeValue m_unzipTime;
	CTimeValue m_startTime;

	// Time in seconds it took to complete the file request.
	float m_completionTime;

	IAsyncIOFileCallback* m_pCallback;

	// If request come from stream, it will be not 0.
	IReadStreamPtr m_pReadStream;

	static uint64 s_nSequenceCounter;
};
TYPEDEF_AUTOPTR(CAsyncIOFileRequest);

#endif //StreamAsyncFileRequest